define(["dojo/_base/declare", "esri/layers/layer", "dojo/dom-construct", "esri/geometry/Point", "dojo/_base/config", "dojo/on"],
    function (declare, Layer, domConstruct, Point, config, on) {
        return declare([Layer], {
            constructor: function (p) {
                dojo.safeMixin(this, p);
                this.loaded = true;
                this.onLoad(this);
            },
            _setMap: function (map, container) {
                this.map = map;
                this.canvas = domConstruct.create("canvas", {
                    id: "canvas",
                    width: map.width + "px",
                    height: map.height + "px",
                    style: "position: absolute; left: 0px; top: 0px;z-index:1;"
                }, container);
                var self = this;
                this.removeHandle();
                this._extentChangeHandle = map.on("extent-change", function () {
                    self.refresh();
                });
                this._panStartHandle = map.on('pan-start', () => {
                    this.canvas.style.display = 'none';
                });
                // this._panEndHandle = map.on('pan-end', () => {
                //     if (!this.visible) {
                //         this.canvas.style.display = 'none';
                //         return;
                //     }
                //     ;
                // });
                this._zoomStartHandle = map.on('zoom-start', () => {
                    this.canvas.style.display = 'none';
                });
                // this._zoomEndHandle = map.on('zoom-end', () => {
                //     if (!this.visible) {
                //         this.canvas.style.display = 'none';
                //         return;
                //     }
                //     ;
                // });
                return this.canvas;
            },
            _unsetMap: function (map, container) {
                if (this.canvas) {
                    container.removeChild(this.canvas);
                }
                this.canvas = null;
                this.removeHandle();
            },
            removeHandle: function () {
                if (this._extentChangeHandle) {
                    this._extentChangeHandle.remove();
                    this._extentChangeHandle = null;
                }
                ;
                if (this._panStartHandle) {
                    this._panStartHandle.remove();
                    this._panStartHandle = null;
                }
                ;
                // if (this._panEndHandle) {
                //     this._panEndHandle.remove();
                //     this._panEndHandle = null;
                // }
                // ;
                if (this._zoomStartHandle) {
                    this._zoomStartHandle.remove();
                    this._zoomStartHandle = null;
                }
                ;
                // if (this._zoomEndHandle) {
                //     this._zoomEndHandle.remove();
                //     this._zoomEndHandle = null;
                // }
                // ;
            },
            data: [],
            canvas: null,
            refresh: function () {
                var me = this;
                if (!this.visible) {
                    return;
                }
                ;

                if (this.canvas && this.mapv) {
                    if (this.map) {
                        this.setScale(this.map, this.canvas);
                    }
                    ;
                    if (!this._elementVisible) {
                        return;
                    }
                    ;
                    me.percent = 0;
                    this.canvas.width = this.map.width;
                    this.canvas.height = this.map.height;
                    var ctx = this.canvas.getContext('2d');
                    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
                    this.canvasResolutionScale(ctx);

                    var item = null;
                    for (var i = 0, len = this.data.length; i < len; i++) {
                        item = this.data[i];
                        var point1 = new Point(item.from[this.lngFieldName], item.from[this.latFieldName]);
                        var start = this.map.toScreen(point1);
                        var point2 = new Point(item.to[this.lngFieldName], item.to[this.latFieldName]);
                        var end = this.map.toScreen(point2);
                        var options = item.symbol || me.symbol;
                        this.canvasDrawCurvemap(ctx, [start.x, start.y], [end.x, end.y], options);
                    }
                }
            },
            canvasResolutionScale: function (context) {
                var devicePixelRatio = this.devicePixelRatio || 1;
                context.canvas.width = context.canvas.width * devicePixelRatio;
                context.canvas.height = context.canvas.height * devicePixelRatio;
                context.canvas.style.width = context.canvas.width / devicePixelRatio + 'px';
                context.canvas.style.height = context.canvas.height / devicePixelRatio + 'px';
                context.scale(devicePixelRatio, devicePixelRatio);
            },
            canvasDrawCurvemap: function (ctx, start, end, options) {
                var me = this;
                ctx.strokeStyle = options.strokeStyle || '#a6c84c';
                ctx.lineWidth = options.lineWidth || 1;
                ctx.setLineDash(options.lineDash || []);
                ctx.beginPath();
                me.drawCurvePath(ctx, start, end, me.curveness, me.percent);
                ctx.stroke();
                me.percent = ( me.percent + 1 ) % 100;
                if (me.percent < 99) {
                    me.canvasDrawCurvemap(ctx, start, end, options);
                }
                ;
            },
            drawCurvePath(ctx, start, end, curveness, percent) {

                var cp = [
                    ( start[0] + end[0] ) / 2 - ( start[1] - end[1] ) * curveness,
                    ( start[1] + end[1] ) / 2 - ( end[0] - start[0] ) * curveness
                ];

                var t = percent / 100;

                var p0 = start;
                var p1 = cp;
                var p2 = end;

                var v01 = [p1[0] - p0[0], p1[1] - p0[1]];     // 向量<p0, p1>
                var v12 = [p2[0] - p1[0], p2[1] - p1[1]];     // 向量<p1, p2>

                var q0 = [p0[0] + v01[0] * t, p0[1] + v01[1] * t];
                var q1 = [p1[0] + v12[0] * t, p1[1] + v12[1] * t];

                var v = [q1[0] - q0[0], q1[1] - q0[1]];       // 向量<q0, q1>

                var b = [q0[0] + v[0] * t, q0[1] + v[1] * t];

                ctx.moveTo(p0[0], p0[1]);

                ctx.quadraticCurveTo(
                    q0[0], q0[1],
                    b[0], b[1]
                );
            },
            visible: true,
            _elementVisible: true,
            setVisibility: function (visible) {
                this.visible = visible;
                if (this.canvas) {
                    if (visible) {
                        // this.refresh();
                        this.canvas.style.display = "block";
                    } else {
                        this.canvas.style.display = "none";
                    }
                    ;
                }
            },
            hideLayer: function () {
                this.visible = false;
                this._elementVisible = false;
                this.canvas.style.display = 'none';
            },
            showLayer: function () {
                this.visible = true;
                this._elementVisible = true;
                this.canvas.style.display = 'block';
                this.refresh();
            },
            removeLayer: function () {
                this.canvas.parentNode.removeChild(this.canvas)
            },
            setScale: function (map, _element) {
                var scale = map.getScale();

                if (this.options && this.options.minScale && this.options.maxScale) {
                    if (scale > this.options.minScale || scale < this.options.maxScale) {
                        _element.style.display = 'none';
                        this._elementVisible = false;
                    } else {
                        _element.style.display = 'block';
                        this._elementVisible = true;
                    }
                    ;
                } else if (this.options && this.options.minScale > 0) {
                    if (scale > this.options.minScale) {
                        _element.style.display = 'none';
                        this._elementVisible = false;
                    } else {
                        _element.style.display = 'block';
                        this._elementVisible = true;
                    }
                    ;
                } else if (this.options && this.options.maxScale > 0) {
                    if (scale < this.options.maxScale) {
                        _element.style.display = 'none';
                        this._elementVisible = false;
                    } else {
                        _element.style.display = 'block';
                        this._elementVisible = true;
                    }
                    ;
                } else {
                    _element.style.display = 'block';
                    this._elementVisible = true;
                }
                ;
            }
        });
    });